# HTML

During the build process, Rsbuild will compile based on the HTML template and template parameters to generate several HTML files.

Rsbuild provides some configs to set the HTML template. Through this chapter, you can learn the basic usage of these configs.

## Set template

In Rsbuild, you can use [html.template](/config/html/template) config to define the path to the custom HTML template.

```ts
export default {
  html: {
    template: './static/index.html',
  },
};
```

If `html.template` is not set, Rsbuild will use the built-in HTML template:

```html title="defaultTemplate.html"
<!doctype html>
<html>
  <head></head>
  <body>
    <div id="<%= mountId %>"></div>
  </body>
</html>
```

## Set page title

You can set the HTML `<title>` tag through the [html.title](/config/html/title) config.

When there is only one page in your project, just use the `html.title` setting directly:

```ts
export default {
  html: {
    title: 'example',
  },
};
```

When your project has multiple pages, you can set corresponding titles for different pages based on the entry name.

```ts
export default {
  html: {
    title({ entryName }) {
      const titles = {
        foo: 'Foo',
        bar: 'Bar',
      };
      return titles[entryName];
    },
  },
};
```

:::tip
For single-page applications (SPA), Rsbuild will include an initial title in the HTML page, but you usually need to dynamically update the page title on route switching, for example using some routing libraries or libraries like [React Helmet](https://github.com/nfl/react-helmet).
:::

## Set page icon

Rsbuild supports setting [favicon](https://developer.mozilla.org/en-US/docs/Glossary/Favicon) icon and [apple-touch-icon](https://webhint.io/docs/user-guide/hints/hint-apple-touch-icons/) icon.

You can set the favicon through the [html.favicon](/config/html/favicon) config.

```ts
export default {
  html: {
    favicon: './src/assets/icon.png',
  },
};
```

You can also set the web application icons to display when added to the home screen of a mobile device through the [html.appIcon](/config/html/app-icon) config.

```ts
export default {
  html: {
    appIcon: {
      name: 'My Website',
      icons: [
        { src: './src/assets/logo-192.png', size: 192 },
        { src: './src/assets/logo-512.png', size: 512 },
      ],
    },
  },
};
```

## Set meta tags

You can set the meta tags through the [html.meta](/config/html/meta) config.

Rsbuild defaults to setting the charset and viewport meta tags:

```html
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
```

You can also add custom meta tags, such as setting the description:

```ts
export default {
  html: {
    meta: {
      description: 'a description of the page',
    },
  },
};
```

The generated meta tag in HTML is:

```html
<meta name="description" content="a description of the page" />
```

## Default template engine

Rsbuild comes with a built-in default template engine to handle HTML template files, and its syntax is similar to a subset of EJS, but it has some differences. When the suffix of an HTML template file is `.html`, Rsbuild will use the built-in template engine to parse the HTML template.

For example, if a `text` param is defined in the template with the value `'world'`, Rsbuild will automatically replace `<%= text %>` with the specified value during the build process.

```html
<!-- Input  -->
<div>hello <%= text %>!</div>

<!-- Output -->
<div>hello world!</div>
```

### Template parameters

In HTML templates, you can use a variety of template parameters. The template parameters injected by Rsbuild by default include:

```ts
type DefaultParameters = {
  mountId: string; // the value of `html.mountId` config
  entryName: string; // entry name
  assetPrefix: string; // the value of dev.assetPrefix or output.assetPrefix configs
  compilation: Compilation; // Compilation object of Rspack
  rspackConfig: Rspack.Configuration; // Rspack config object
  // generated by html-rspack-plugin
  htmlPlugin: {
    tags: {
      headTags: HtmlTagObject[];
      bodyTags: HtmlTagObject[];
    };
    files: {
      publicPath: string;
      js: Array<string>;
      css: Array<string>;
      favicon?: string;
    };
  };
};
```

You can use the [html.templateParameters](/config/html/template-parameters) config to pass in custom template parameters. For example:

```ts title="rsbuild.config.ts"
export default {
  html: {
    templateParameters: {
      text: 'world',
    },
  },
};
```

Then you can read parameters in the HTML template with `<%= text %>`:

```html title="index.html"
<div>hello <%= text %>!</div>
```

The compiled HTML code will be:

```html title="dist/index.html"
<div>hello world!</div>
```

### Parameter escaping

When using `<%= text %>`, the parameters will not be escaped. You can use `<%- text %>` to escape parameters.

For example, if the value of the parameter `text` is `'<script>'`, it will be escaped to `&lt;script&gt;`:

```html
<!-- Input  -->
<div>hello <%- text %>!</div>

<!-- Output -->
<div>hello &lt;script&gt;!</div>
```

:::tip
Note that Rsbuild's default escape syntax is different from EJS. In EJS, the default escape syntax is `<%= text %>`, whereas Rsbuild's default escape syntax is `<%- text %>`.
:::

### Conditional statements

- if condition:

```ts title="rsbuild.config.ts"
export default {
  html: {
    templateParameters: {
      show: true,
    },
  },
};
```

```ejs
<% if (show) { %>
<p>show is true</p>
<% } %>
```

- if/else condition:

```ejs
<% if (show) { %>
<p>show is true</p>
<% } else { %>
<p>show is false</p>
<% } %>
```

- else if condition:

```ts title="rsbuild.config.ts"
export default {
  html: {
    templateParameters: {
      count: 7,
    },
  },
};
```

```ejs
<% if (count > 10) { %>
<p>count > 10</p>
<% } else if (count > 5) { %>
<p>count > 5</p>
<% } else { %>
<p>count ≤ 5</p>
<% } %>
```

- Nested conditions:

```ts title="rsbuild.config.ts"
export default {
  html: {
    templateParameters: {
      parent: true,
      child: true,
    },
  },
};
```

```ejs
<% if (parent) { %>
<p>parent is true</p>
  <% if (child) { %>
  <p>child is true</p>
  <% } %>
<% } %>
```

- Ternary operator:

```ts title="rsbuild.config.ts"
export default {
  html: {
    templateParameters: {
      show: true,
      value: 'success',
    },
  },
};
```

```ejs
<p>result: <%= show ? value : 'none' %></p>
```

### Loop statements

- for loop:

```ts title="rsbuild.config.ts"
export default {
  html: {
    templateParameters: {
      items: ['Item 1', 'Item 2', 'Item 3'],
    },
  },
};
```

```ejs title="index.html"
<ul>
  <% for (let i = 0; i < items.length; i++) { %>
  <li><%= items[i] %></li>
  <% } %>
</ul>
```

- forEach loop:

```ejs title="index.html"
<ul>
  <% items.forEach(function(item, index) { %>
  <li><%= item %> <%= index %></li>
  <% }); %>
</ul>
```

- for...of loop:

```ejs title="index.html"
<ul>
  <% for (let item of items) { %>
  <li><%= item %></li>
  <% } %>
</ul>
```

## Other template engines

Rsbuild also supports using other template engines via plugins, such as [EJS](https://ejs.co/) and [Pug](https://pugjs.org/).

### EJS

Rsbuild's built-in template syntax has some differences from [EJS](https://ejs.co/). To use the full EJS syntax, you can support it through a plugin. See [rsbuild-plugin-ejs](https://github.com/rspack-contrib/rsbuild-plugin-ejs) for more details.

### Pug

Rsbuild supports the [Pug](https://pugjs.org/) template engine via a plugin. See [@rsbuild/plugin-pug](https://github.com/rspack-contrib/rsbuild-plugin-pug) for more details.

## Injecting tags

You can insert any tags into the HTML files generated by Rsbuild by configuring [html.tags](/config/html/tags).

In the HTML template, the `htmlPlugin.tags` variable gives you access to all the tags inserted into the HTML:

```html title="index.html"
<html>
  <head>
    <%= htmlPlugin.tags.headTags %>
  </head>
  <body>
    <div id="root"></div>
    <%= htmlPlugin.tags.bodyTags %>
  </body>
</html>
```

The purpose of the `html.tags` is to update these tag variables to modify the tags in the HTML. Here is a basic example:

```ts
export default {
  html: {
    tags: [
      { tag: 'script', attrs: { src: 'https://cdn.example.com/my-script.js' } },
    ],
  },
};
```

- The generated HTML file looks like this:

```html
<html>
  <head>
    <script src="https://cdn.example.com/my-script.js"></script>
    <!-- some other headTags... -->
  </head>
  <body>
    <!-- some other bodyTags... -->
  </body>
</html>
```

> For more usage, please refer to: [html.tags](/config/html/tags).

:::tip
Typically, you do not need to manually use the `htmlPlugin.tags.headTags` and `htmlPlugin.tags.bodyTags` template parameters, because Rsbuild will automatically inject these tags. See [html.inject](/config/html/inject) for more details on adjusting the injection location.
:::

## HTML plugin

Rsbuild internally implements HTML-related features based on [html-rspack-plugin](https://github.com/rspack-contrib/html-rspack-plugin). It is a fork of [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin), with the same features and options.

You can modify the html-rspack-plugin options via [tools.htmlPlugin](/config/tools/html-plugin), or disable the default html-rspack-plugin.

For example:

```ts title="rsbuild.config.ts"
export default {
  tools: {
    htmlPlugin(config, { entryName }) {
      if (process.env.NODE_ENV === 'production') {
        config.filename = `${entryName}.[contenthash:8].html`;
      }
    },
  },
};
```

## HTML minification

Rsbuild currently does not minify HTML files. If you need to minify HTML files, you can use the [rsbuild-plugin-html-minifier-terser plugin](https://github.com/rspack-contrib/rsbuild-plugin-html-minifier-terser).
